home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- //
- // DataPath.cxx - Data Path for the Hector 1600 CPU
- //
- // By: Bradford W. Mott
- // December 3,1993
- //
- ///////////////////////////////////////////////////////////////////////////////
-
- #include "DataPath.hxx"
-
- ///////////////////////////////////////////////////////////////////////////////
- // The Constructor
- ///////////////////////////////////////////////////////////////////////////////
- DataPath::DataPath(BasicCPU* c)
- : cpu(c)
- {
- ResetSignals();
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // The Destructor
- ///////////////////////////////////////////////////////////////////////////////
- DataPath::~DataPath()
- {
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Reset the data path signals
- ///////////////////////////////////////////////////////////////////////////////
- void DataPath::ResetSignals()
- {
- // Reset all of the data path signals used for each clock cycle
- MAR_SEL = MDR_SEL = NONE;
- ALU_FN = DO_NOTHING;
- MDR_LATCH = MAR_LATCH = IR_LATCH = 0;
- MAR_OUT_EN = MDR_OUT_EN = 0;
- A_SEL = B_SEL = -1;
- WRT_A = WRT_B = DB_GT = ALU_GT = 0;
- }
-
- void DataPath::a_sel(int reg)
- { A_SEL=reg; }
-
- void DataPath::b_sel(int reg)
- { B_SEL=reg; }
-
- void DataPath::wrt_a()
- { WRT_A=1; }
-
- void DataPath::wrt_b()
- { WRT_B=1; }
-
- void DataPath::db_gt()
- { DB_GT=1; }
-
- void DataPath::alu_gt()
- { ALU_GT=1; }
-
- void DataPath::alu_fn(ALUFunction function)
- { ALU_FN=function; }
-
- void DataPath::mdr_sel(DataPathBus bus)
- { MDR_SEL=bus; }
-
- void DataPath::mdr_latch()
- { MDR_LATCH=1; }
-
- void DataPath::mdr_out_en()
- { MDR_OUT_EN=1; }
-
- void DataPath::mar_sel(DataPathBus bus)
- { MAR_SEL=bus; }
-
- void DataPath::mar_latch()
- { MAR_LATCH=1; }
-
- void DataPath::mar_out_en()
- { MAR_OUT_EN=1; }
-
- void DataPath::ir_latch()
- { IR_LATCH=1; }
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // Read a word from memory
- ///////////////////////////////////////////////////////////////////////////////
- int DataPath::Peek(unsigned long address, unsigned int& value)
- {
- unsigned char b1,b2;
- address *= cpu->Granularity();
-
- if(!cpu->address_space[0].Peek(address,b1))
- return(0);
-
- if(!cpu->address_space[0].Peek(address+1,b2))
- return(0);
-
- value=((unsigned long)b1 << 8) | (unsigned long)b2;
-
- return(1);
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // Write a word to memory
- ///////////////////////////////////////////////////////////////////////////////
- int DataPath::Poke(unsigned long address, unsigned int value)
- {
- unsigned char b1,b2;
- address *= cpu->Granularity();
-
- b1=value >> 8;
- b2=value;
-
- if(!cpu->address_space[0].Poke(address,b1))
- return(0);
-
- if(!cpu->address_space[0].Poke(address+1,b2))
- return(0);
-
- return(1);
- }
-
-
-
- ///////////////////////////////////////////////////////////////////////////////
- // Called at the end of each cycle to perform the actual cycle operations
- ///////////////////////////////////////////////////////////////////////////////
- const char* DataPath::Clock()
- {
- // Put the selected registers onto the A & B Bus
- if(A_SEL >= 0)
- a_bus = register_set.GetRegister(A_SEL);
- if(B_SEL >= 0)
- b_bus = register_set.GetRegister(B_SEL);
-
- // Do the ALU Function
- if(ALU_FN != DO_NOTHING)
- alu_bus = alu.Compute(ALU_FN, a_bus, b_bus);
-
- // If mar_latch is set, put the appropriate bus contents into MAR
- if(MAR_LATCH) {
- switch (MAR_SEL) {
- case A_BUS:
- mar = a_bus;
- break;
- case B_BUS:
- mar = b_bus;
- break;
- case ALU_BUS:
- mar = alu_bus;
- break;
- default: // mar_latch was set but mar_sel wasn't called
- return("Simulator Logic Error: No mar_sel");
- }
- }
-
- // If mdr_latch is set, put the appropriate bus contents into MDR
- if(MDR_LATCH) {
- switch (MDR_SEL) {
- case A_BUS:
- mdr = a_bus;
- break;
- case B_BUS:
- mdr = b_bus;
- break;
- case ALU_BUS:
- mdr = alu_bus;
- break;
- default: // mdr_latch was set but mdr_sel wasn't called
- return("Simulator Logic Error: No mdr_sel");
- }
- }
-
- // Memory read
- if(MAR_OUT_EN && !MDR_OUT_EN)
- {
- // read the data onto the DATA_BUS
- if(!Peek(mar, data_bus))
- return("Bus Error");
-
- // bump the read cycle counter
- number_of_reads++;
- }
-
- // Memory write
- if(MAR_OUT_EN && MDR_OUT_EN) {
- // write the contents of MDR to the location pointed to by MAR
- if(!Poke(mar, mdr))
- return("Bus Error");
-
- // bump the write cycle counter
- number_of_writes++;
- }
-
- // If ir_latch is set, load the DATA_BUS into the IR
- if(IR_LATCH)
- ir = data_bus;
-
- // Make sure there isn't write bus contention
- if(DB_GT && ALU_GT)
- return("Simulator Logic Error: WRT_BUS Contention");
-
- // Set the WRT_BUS if a signal is gated thru to it
- if(DB_GT)
- wrt_bus = data_bus;
- else if(ALU_GT)
- wrt_bus = alu_bus;
-
- // Write the source and/or destination regs if specified
- if(WRT_A)
- register_set.SetRegister(A_SEL, wrt_bus);
- if(WRT_B)
- register_set.SetRegister(B_SEL, wrt_bus);
-
- // Bump the cycle counter
- number_of_cycles++;
-
- // Reset the signals
- ResetSignals();
-
- // No Error! So return NULL pointer...
- return((void*)0);
- }
-
-